#ifndef ___SHAREDMEMORY__H__
#define ___SHAREDMEMORY__H__

#define ERROR_FTOK 	-1
#define ERROR_SHMGET 	-2
#define ERROR_SHMAT 	-3
#define OK 0

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string>

#include <iostream>

using namespace std;


template <class T> class SharedMemory{

	private:
		int fd;		//Archivo para generar la clave
		int shmid;	//Memoria compartida
		T* ptrDatos;	//Tipo de dato 
	
	public:	
		SharedMemory(char* nombre,int *estado=NULL);
		~SharedMemory();
		void escribir(T dato);
		T leer();

	friend ostream& operator<<(ostream &stream,SharedMemory<T> &sh);
};


template <class T> SharedMemory<T>::SharedMemory(char* nombre,int *estado){
	
	key_t clave = ftok(nombre,'r');

	if(clave==-1 && estado !=NULL)
		*estado=ERROR_FTOK;
		
	if(clave==-1)
		cout<<"error al crear la clave de sharedmemory ("<< nombre <<")"<<endl;
 
	this->shmid = shmget(clave, sizeof(T), IPC_CREAT | 0666 );

	if(this->shmid==-1 && estado !=NULL)
		*estado=ERROR_SHMGET;

	void* temp = shmat(this->shmid, NULL, 0);

	if(temp==(void *)-1 && estado !=NULL)
		*estado=ERROR_SHMAT;
	
	this->ptrDatos=(T *)temp;

	if (estado != NULL)
		*estado = OK;
	
} 

template <class T> SharedMemory<T>::~SharedMemory(){
	shmdt((void *)this->ptrDatos);
	shmctl(this->shmid,IPC_RMID,NULL);
}

template <class T> void SharedMemory<T>::escribir(T dato){
	*(this->ptrDatos)=dato;
}

template <class T> T SharedMemory<T>::leer(){
	return *(this->ptrDatos);
}

template <class T> ostream& operator<< (ostream &stream,SharedMemory<T> &sh)
{	stream<<sh.leer();
	return stream;
}  

#endif


